package ai.zixing.mashibing.basic_class.class06;

import java.util.HashMap;
import java.util.Map;

public class Code04_CopyListWithRandom {

    // 额外空间复杂度为O(N)
    public static Node copyListWithRand1(Node head) {
        Map<Node, Node> map = new HashMap<>();
        Node cur = head;
        while (cur != null) {
            map.put(cur, new Node(cur.value));
            cur = cur.next;
        }
        cur = head;
        while (cur != null) {
            map.get(cur).next = map.get(cur.next);
            map.get(cur).rand = map.get(cur.rand);
            cur = cur.next;
        }
        return map.get(head);
    }

    public static Node copyListWithRand2(Node head) {
        if (head == null) {
            return null;
        }
        Node cur = head;
        Node next = null;
        // 复制每个节点，连到它的后面
        // 1 -> 2
        // 1 -> 1' -> 2
        while (cur != null) {
            next = cur.next;
            cur.next = new Node(cur.value);
            cur.next.next = next;
            cur = next;
        }

        // 处理复制后的 rand 节点
        cur = head;
        Node copy = null;
        while (cur != null) {
            // 下一个老的节点
            next = cur.next.next;

            //  cur 是老的节点
            // cur.next 是老节点的复制节点
            copy = cur.next;
            // 复制节点的rand指针是老rand节点的下一个节点
            copy.rand = cur.rand == null ? null : cur.rand.next;
            cur = next;
        }

        // 将新链表分离出来
        cur = head;
        Node resNode = cur.next;
        while (cur != null) {
            // 下一个老节点
            next = cur.next.next;
            // 复制节点
            copy = cur.next;
            // 恢复老链表
            cur.next = next;
            // 获取新链表
            copy.next = next == null ? null : next.next;
            cur = next;
        }
        return resNode;
    }


    public static void printRandLinkedList(Node head) {
        Node cur = head;
        System.out.println("order: ");
        while (cur != null) {
            System.out.print(cur.value + " ");
            cur = cur.next;
        }
        System.out.println();
        cur = head;
        System.out.print("rand:  ");
        while (cur != null) {
            System.out.print(cur.rand == null ? "- " : cur.rand.value + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Node head = null;
        Node res1 = null;
        Node res2 = null;
        printRandLinkedList(head);
        res1 = copyListWithRand1(head);
        printRandLinkedList(res1);
        res2 = copyListWithRand2(head);
        printRandLinkedList(res2);
        printRandLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(4);
        head.next.next.next.next = new Node(5);
        head.next.next.next.next.next = new Node(6);

        head.rand = head.next.next.next.next.next; // 1 -> 6
        head.next.rand = head.next.next.next.next.next; // 2 -> 6
        head.next.next.rand = head.next.next.next.next; // 3 -> 5
        head.next.next.next.rand = head.next.next; // 4 -> 3
        head.next.next.next.next.rand = null; // 5 -> null
        head.next.next.next.next.next.rand = head.next.next.next; // 6 -> 4

        printRandLinkedList(head);
        res1 = copyListWithRand1(head);
        printRandLinkedList(res1);
        res2 = copyListWithRand2(head);
        printRandLinkedList(res2);
        printRandLinkedList(head);
        System.out.println("=========================");
    }
}
